package com.CustomControl;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Vector;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;

import com.DataStructure.Node;
import com.DataStructure.Tile;
import com.Database.DBAdapter;
import com.Activity.R;

public class MyImageView extends ImageView implements Runnable {

	private ArrayList<Tile> tiles = null;
	DBAdapter db;
	private int slided_x = 0;
	private int slided_y = 0;
	private int center_tile_x;
	private int center_tile_y;
	public static final int WIDTH = 0;
	public static final int HEIGH = 1;
	private int zoom_lv;
	Thread t = null;
	Bitmap[] markers_img = new Bitmap[11];
	public Vector<Node> markerVtr = new Vector<Node>();
	Vector<Node> path = new Vector<Node>();
	Paint paint = new Paint();

	public MyImageView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public MyImageView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public MyImageView(Context context) {
		super(context);
	}

	public void setValue(ArrayList<Tile> tiles, int center_id_tile_x,
			int center_id_tile_y, int z_default, int delta_x, int delta_y) {
		this.tiles = tiles;
		this.center_tile_x = center_id_tile_x * 256;
		this.center_tile_y = center_id_tile_y * 256;
		zoom_lv = z_default;
		this.scrollBy(this.center_tile_x - slided_x - delta_x,
				this.center_tile_y - slided_y - delta_y);
		if (t == null) {
			t = new Thread(this);
			t.start();
		}
	}

	public void setPath(Vector<Node> path) {
		this.path = path;
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if (tiles != null) {
			if (!tiles.isEmpty()) {
				float left = 0, top = 0;

				for (Tile tile : tiles) {
					int x = tile.getX();
					int y = tile.getY();
					left = x * 256;
					top = y * 256;
					Bitmap image_tile = tile.getImage();
					canvas.drawBitmap(image_tile, left, top, null);
				}
				for (int i = 0; i < markerVtr.size(); i++) {
					Node marker = markerVtr.elementAt(i);
					canvas.drawBitmap(getMarker(i),
							marker.getMarkerX(zoom_lv) - 13,
							marker.getMarkerY(zoom_lv) - 44, null);
				}
				if (!path.isEmpty()) {
					paint.setColor(Color.BLUE);
					for (int i = 0, size = path.size() - 1; i < size; i++) {
						canvas.drawLine(path.elementAt(i).getMarkerX(zoom_lv),
								path.elementAt(i).getMarkerY(zoom_lv), path
										.elementAt(i + 1).getMarkerX(zoom_lv),
								path.elementAt(i + 1).getMarkerY(zoom_lv),
								paint);
					}
				}
			}
		}
	}

	@Override
	public void setImageBitmap(Bitmap bm) {
		super.setImageBitmap(bm);
	}

	@Override
	protected void onScrollChanged(int l, int t, int oldl, int oldt) {
		slided_x = slided_x + l - oldl;
		slided_y = slided_y + t - oldt;
	}

	public void setDBAdapter(DBAdapter db) {
		this.db = db;
	}

	public int getCenterTileX() {
		return center_tile_x;
	}

	public int getCenterTileY() {
		return center_tile_y;
	}

	@Override
	public void run() {
		while (true) {
			ArrayList<Tile> modifyTilesX = null;
			if (slided_x - 256 >= center_tile_x) {
				modifyTilesX = db.getTiles(1, center_tile_x, center_tile_y,
						WIDTH, zoom_lv);
				for (int i = 0; i < tiles.size(); i++) {
					Tile temp = tiles.get(i);
					if (temp.getX() * 256 < center_tile_x - 256) {
						for (int j = 0; j < modifyTilesX.size(); j++) {
							if (modifyTilesX.get(j).getY() == temp.getY()) {
								temp.setX(temp.getX() + 5);
								temp.setImage(modifyTilesX.remove(j).getImage());
								break;
							}

						}
						if (modifyTilesX.isEmpty())
							break;
					}
				}
				center_tile_x = center_tile_x + 256;
			} else if (slided_x + 256 < center_tile_x) {
				modifyTilesX = db.getTiles(-1, center_tile_x, center_tile_y,
						WIDTH, zoom_lv);
				for (int i = 0; i < tiles.size(); i++) {
					Tile temp = tiles.get(i);
					if (temp.getX() * 256 > center_tile_x + 256) {
						for (int j = 0; j < modifyTilesX.size(); j++) {
							if (modifyTilesX.get(j).getY() == temp.getY()) {
								temp.setX(temp.getX() - 5);
								temp.setImage(modifyTilesX.remove(j).getImage());
								break;
							}

						}
						if (modifyTilesX.isEmpty())
							break;
					}
				}
				center_tile_x = center_tile_x - 256;
			}

			ArrayList<Tile> modifyTilesY = null;
			if (slided_y - 256 > center_tile_y) {
				modifyTilesY = db.getTiles(1, center_tile_x, center_tile_y,
						HEIGH, zoom_lv);
				for (int i = 0; i < tiles.size(); i++) {
					Tile temp = tiles.get(i);
					if (temp.getY() * 256 < center_tile_y - 256) {
						for (int j = 0; j < modifyTilesY.size(); j++) {
							if (modifyTilesY.get(j).getX() == temp.getX()) {
								temp.setY(temp.getY() + 5);
								temp.setImage(modifyTilesY.remove(j).getImage());
								break;
							}

						}
						if (modifyTilesY.isEmpty())
							break;
					}
				}
				center_tile_y = center_tile_y + 256;
			} else if (slided_y + 256 < center_tile_y) {
				modifyTilesY = db.getTiles(-1, center_tile_x, center_tile_y,
						HEIGH, zoom_lv);
				for (int i = 0; i < tiles.size(); i++) {
					Tile temp = tiles.get(i);
					if (temp.getY() * 256 > center_tile_y + 256) {
						for (int j = 0; j < modifyTilesY.size(); j++) {
							if (modifyTilesY.get(j).getX() == temp.getX()) {
								temp.setY(temp.getY() - 5);
								temp.setImage(modifyTilesY.remove(j).getImage());
								break;
							}

						}
						if (modifyTilesY.isEmpty())
							break;
					}
				}
				center_tile_y = center_tile_y - 256;
			}

			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public int getSlidedX() {
		return slided_x;
	}

	public int getSlidedY() {
		return slided_y;
	}

	private Bitmap getMarkerImg() {
		Bitmap marker_img = null;
		InputStream in;
		BufferedInputStream buf;
		try {
			in = getResources().openRawResource(R.drawable.red_markers);
			buf = new BufferedInputStream(in);
			byte[] bMapArray = new byte[buf.available()];
			buf.read(bMapArray);
			marker_img = BitmapFactory.decodeByteArray(bMapArray, 0,
					bMapArray.length);
			if (in != null) {
				in.close();
			}
			if (buf != null) {
				buf.close();
			}
		} catch (Exception e) {
			Log.e("Error reading file", e.toString());
		}
		return marker_img;
	}

	public Bitmap getMarker(int id) {
		if (id > 10) {
			id = 10;
		}
		if (markers_img[id] == null) {
			int[] pixels = new int[26 * 484];
			getMarkerImg().getPixels(pixels, 0, 26, 0, 0, 26, 484);

			for (int i = 0; i < 11; i++) {
				markers_img[i] = Bitmap.createBitmap(pixels, i * 26 * 44, 26,
						26, 44, getMarkerImg().getConfig());
			}
		}
		return markers_img[id];
	}

	public void insertMarker(Node marker) {
		markerVtr.add(marker);
	}
}
